import ComponentInstance from './componentInstance';
import StorageHelper from '../Runtime/Global/storage';
import { RUNTIME_CFG_ENUM } from '../Runtime/Global/variable';
import {
	// ComponentStateHelper,
	getUniqueVersionName
} from '@CIF/ComponentLoader/dynamicComponentLoader.js';
import { ComponentDefinitionHelper } from '../ComponentTemplate/componentDefinition';
import { ComponentLibraryHelper } from '../ComponentTemplate/componentLibrary';
import { uuid, zip, unzip } from '@CIF/Utils/util';
import Notifier from '@CIF/Utils/Notifier';
import _ from 'lodash';
// import { createApp } from 'vue';

const ComponentTreeNodeCache = {};
// const Vue = createApp();
export const ComponentTreeNodeTypeEnum = {
	NORMAL: 0,
	CONTAINER: 1,
	FOLDER: 2
};

/**
 * 组件树节点结构
 */
class ComponentTreeNode {
	uuid = '';

	/**
	 * 组件树节点名
	 *
	 * @memberof ComponentTreeNode
	 */
	name = '组件树节点名';
	/**
	 * 组件节点类型，枚举：0（普通组件）、1（容器类组件）、2（文件夹）
	 *
	 * @memberof ComponentTreeNode
	 */
	nodeType = ComponentTreeNodeTypeEnum.FOLDER;
	/**
	 * 容器组件子组件数组
	 *
	 * @memberof ComponentTreeNode
	 */
	children = [];

	isBroken = false;

	componentInstance = undefined;

	#cpntLibEntryRef = null;
	#cpntDefRef = null;

	constructor(treeNode) {
		if (treeNode.children) {
			this.children = treeNode.children.map((x) => {
				try {
					return new ComponentTreeNode(x);
				} catch (error) {
					x.isBroken = true;
					if (_.get(window, 'cif.config.logger.enable', false) === true) {
						console.log(
							'CIF.CT.componentTree.ComponentTreeHelper:constructor 初始化组件树节点失败',
							error
						);
					}
					return new ComponentTreeNode(x);
				}
			});
		}
		if (!_.isNil(treeNode.isBroken) && treeNode.isBroken === true) {
			this.isBroken = treeNode.isBroken;
		} else {
			this.isBroken = false;
		}
		if (!treeNode.isBroken && treeNode.componentInstance) {
			if (treeNode.componentInstance instanceof ComponentInstance) {
				this.componentInstance = treeNode.componentInstance;
			} else {
				this.componentInstance = new ComponentInstance(treeNode.componentInstance);
			}
			this.uuid = treeNode.uuid || this.componentInstance.uuid;
			this.name = treeNode.name || this.componentInstance.name;
			this.nodeType =
				treeNode.nodeType ||
				this.componentInstance.definitionRefrence.cpntType ||
				ComponentTreeNodeTypeEnum.NORMAL;
		} else {
			this.uuid = treeNode.uuid || uuid();
			this.name = treeNode.name || '新建文件夹';
			this.nodeType = treeNode.nodeType || ComponentTreeNodeTypeEnum.FOLDER;
		}
		if (this.isBroken === true) {
			Notifier.broadcastInChannel('_damage_cpnt_channel', treeNode.name);
		}

		this.#cpntDefRef = _.get(this, 'componentInstance.definitionRefrence');
		const defId = _.get(this, 'componentInstance.definitionRefrence.id', null);
		if (!_.isNil(defId)) {
			this.#cpntLibEntryRef = ComponentLibraryHelper.getCpntLibEntryFromCache(defId);
		}

		ComponentTreeNodeCache[this.uuid] = this;
	}

	isAllowHasChilds = () => {
		return this.nodeType !== ComponentTreeNodeTypeEnum.NORMAL;
	};

	getIcon = () => {
		if (this.nodeType === ComponentTreeNodeTypeEnum.FOLDER) {
			return null;
		}
		return _.get(this, 'componentInstance.icon', null);
	};

	getCpntLibEntryRef = () => {
		// return _.get(this, "#cpntLibEntryRef", null)
		return this.#cpntLibEntryRef || null;
	};

	getCpntDefRef = () => {
		// return _.get(this, '#cpntDefRef', null);
		return this.#cpntDefRef || null;
	};

	addComponent = (cpntDefineId) => {
		const cpntInstance = new ComponentInstance({ definitionId: cpntDefineId });
		const treeNodeData = {
			uuid: cpntInstance.uuid,
			name: cpntInstance.name,
			nodeType: cpntInstance.definitionRefrence.cpntType,
			componentInstance: cpntInstance
		};
		const cpntTreeNode = new ComponentTreeNode(treeNodeData);
		this.children.push(new ComponentTreeNode(cpntTreeNode));
	};

	addFolder = () => {
		const newTreeNode = new ComponentTreeNode();
		newTreeNode.nodeType = ComponentTreeNodeTypeEnum.FOLDER;
		this.children.push(newTreeNode);
	};

	getDescription = () => {
		const defId = _.get(this, 'componentInstance.definitionRefrence.id', null);
		if (_.isNil(defId)) {
			return null;
		}
		const cpntLibEntry = ComponentLibraryHelper.getCpntLibEntryFromCache(defId);
		return _.get(cpntLibEntry, 'discription', null);
	};
}

/**
 * 当前应用的激活的组件组件图层, 是一个数组，不包含组件树嵌套结构，维护组件的层级信息，主要用于快速存取利用组件层级 z-index
 * @param {*} cpntNavTree
 * @returns
 */
const getTreeFlatLayer = (cpntNavTree = []) => {
	let result = [];
	//循环处理数据
	const detail = (treeNode) => {
		if (treeNode.nodeType !== ComponentTreeNodeTypeEnum.FOLDER) {
			result.push(treeNode);
		}
		if (!_.isNil(treeNode.children) && !_.isEmpty(treeNode.children)) {
			treeNode.children.forEach((childrenTreeNode) => {
				detail(childrenTreeNode);
			});
		}
	};
	cpntNavTree.forEach((treeNode) => {
		detail(treeNode);
	});
	const topZindex = result.length;
	result.forEach((ele, index) => {
		ele.zIndex = topZindex - index;
		// Vue.set(ele, 'zIndex', topZindex - index);
	});
	return result;
};

const getNewTree = () => {
	return [];
};

/**
 * 快速查找树节点，不包含树节点位置信息
 * @param {*} uuid 组件树id
 * @returns
 */
const findTreeNodeQuick = (uuid) => {
	return ComponentTreeNodeCache[uuid];
};

/**
 * 查找组件树节点详情，返回会附带父节点信息，主要用于删除或移动树节点
 * @param { ComponentTreeNode[] } rootTree 组件树
 * @param { String } uuid 组件树id
 * @returns
 */
const findTreeNodeDetail = (rootTree = [], uuid) => {
	//循环处理数据
	let cpntTreeNode = undefined;
	let indexOfParent = 0;
	let parent = undefined;
	let timesToFoundTheTreeNode = 0;
	let parentLength = 0; // 父级元素长度，需要注意父级元素到底是父级节点的children属性还是父级节点本身

	let isFounded = false;

	if (uuid !== '') {
		const detail = (treeNode, parentTreeNode, index, times = 0) => {
			if (isFounded === true) {
				return;
			}
			if (uuid === treeNode.uuid) {
				cpntTreeNode = treeNode;
				parentLength = Array.isArray(parentTreeNode)
					? parentTreeNode.length - 1
					: parentTreeNode.children.length - 1;
				parent = parentTreeNode;
				timesToFoundTheTreeNode = times;
				indexOfParent = index;
				isFounded = true;
				return;
			}
			// 原有逻辑在组件有children字段时直接过滤掉，会导致容器类组件节点和文件夹节点无法查找到，现已进行修正
			const children = treeNode.children;
			if (!_.isEmpty(children)) {
				for (let i = 0; i < children.length; i++) {
					if (isFounded === true) {
						break;
					} else {
						detail(children[i], treeNode, i, times + 1);
					}
				}
			}
		};
		for (let i = 0; i < rootTree.length; i++) {
			if (isFounded === true) {
				break;
			} else {
				detail(rootTree[i], rootTree, i);
			}
		}
	}
	return {
		cpntTreeNode,
		indexOfParent,
		parentLength,
		timesToFoundTheTreeNode,
		parent // parent要么是root数组，要么是treeNode对象
	};
};

/**
 * 初始化组件树
 * @param {String} treeData ComponentTreeNode的json数据
 */
const _initTree = (treeData = '') => {
	try {
		const newTree = [];

		if (treeData === '') {
			return newTree;
		}
		const treeObject = JSON.parse(unzip(treeData));

		treeObject.forEach((ele) => {
			try {
				newTree.push(new ComponentTreeNode(ele));
			} catch (error) {
				// * 初始化时组件树时组件树节点损毁做好损毁标记即可，手动添加组件情况才抛出错误，避免组件树完整初始化过程
				ele.isBroken = true;
				newTree.push(new ComponentTreeNode(ele));
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log(
						'CIF.CT.componentTree.ComponentTreeHelper:initTree 初始化组件树节点失败',
						error
					);
				}
			}
		});
		return newTree;
	} catch (error) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log('CIF.CT.componentTree.ComponentTreeHelper:initTree 初始化组件树失败', error);
		}
		return [];
	}
};

const initTree = (treeData = '') => {
	const result = _initTree(treeData);
	getTreeFlatLayer(result);
	return result;
};

/**
 * 特别用于当前组件树没有选择节点时添加到根节点
 * 当parentNodeId为空字符串时添加到树根
 * @param {ComponentTreeNode[]} rootTree
 * @param {ComponentTreeNode} newNode
 * @param {String} parentNodeId
 */
const _addTreeNodeToTree = (rootTree = [], newNode, parentNodeId = '') => {
	if (!_.isEmpty(parentNodeId)) {
		const cpntTreeNode = findTreeNodeQuick(parentNodeId);
		if (cpntTreeNode) {
			if (cpntTreeNode.isAllowHasChilds()) {
				cpntTreeNode.children.push(newNode);
				return true;
			} else {
				// TODO: 按理来说应该不允许新增，现在暂时处理成新增到父级节点
				// if (Array.isArray(node.parent)) {
				//   node.parent.push(newNode)
				// } else {
				//   node.parent.children.push(newNode)
				// }
				return false;
			}
		} else {
			rootTree.push(newNode);
			return true;
		}
	} else {
		rootTree.push(newNode);
		return true;
	}
};

const addTreeNodeToTree = (rootTree = [], newNode, parentNodeId = '') => {
	const result = _addTreeNodeToTree(rootTree, newNode, parentNodeId);
	getTreeFlatLayer(rootTree);
	return result;
};

/**
 * 组件树通过组件定义id批量添加实例节点辅助函数
 * 特别用于当前组件树没有选择节点时添加到根节点
 * 当parentNodeId为空字符串时添加到树根
 * @param {ComponentTreeNode[]} rootTree
 * @param {String[]} defIds
 * @param {String} parentNodeId
 */
const _addNewInstancesToTreeByDefIds = (rootTree = [], defIds = [], parentNodeId = '') => {
	if (_.get(window, 'cif.config.logger.enable', false) === true) {
		console.log('CIF.CT.componentTree.ComponentTreeHelper:addNewInstancesToTreeByDefIds');
	}
	if (_.isEmpty(defIds)) {
		return false;
	}
	const loader = StorageHelper.get(RUNTIME_CFG_ENUM.DYNAMIC_COPONENT_LOADER);
	if (_.isEmpty(loader)) {
		return false;
	}
	const pushInstToParentByDefIds = (parent = [], defIds = []) => {
		// console.log('parent---------', parent, 'defIds-------', defIds);
		return Promise.allSettled(
			defIds.map((id) => {
				const def = ComponentDefinitionHelper.getDef(id);
				if (def) {
					return new Promise((resolve = () => {}, reject = () => {}) => {
						const versionName = getUniqueVersionName(def);
						// debugger;
						loader
							.load(versionName)
							.then(() => {
								const newTreeNode = new ComponentTreeNode({
									componentInstance: new ComponentInstance({ definitionId: id })
								});
								parent.push(newTreeNode);
								resolve(newTreeNode);
							})
							.catch((e) => {
								console.log('error', e);
								reject(e);
							});
					});
				} else {
					return new Promise((resolve = () => {}, reject = () => {}) => {
						const cpntLibEntry = ComponentLibraryHelper.getCpntLibEntryFromCache(id);
						if (!_.isEmpty(cpntLibEntry)) {
							return loader
								.fetch(cpntLibEntry)
								.then((l) => {
									const versionName = `${cpntLibEntry.moduleName}_${cpntLibEntry.version}`;
									// debugger;
									l.load(versionName)
										.then(() => {
											const newTreeNode = new ComponentTreeNode({
												componentInstance: new ComponentInstance({ definitionId: id })
											});
											parent.push(newTreeNode);
											resolve(newTreeNode);
										})
										.catch((e) => {
											console.log('error', e);
											reject(e);
										});
								})
								.catch((e) => {
									reject(e);
								});
						} else {
							return Promise.reject(`组件库数据中未寻获id为${id}的组件!`);
						}
					});
				}
			})
		);
	};
	try {
		if (!_.isEmpty(parentNodeId)) {
			const cpntTreeNode = findTreeNodeQuick(parentNodeId);
			if (cpntTreeNode) {
				if (cpntTreeNode.isAllowHasChilds()) {
					return pushInstToParentByDefIds(cpntTreeNode.children, defIds);
				} else {
					// pushInstToParentByDefIds(node.parent, defIds)
					// return true
					throw new Error('普通类型组件无法添加子组件');
				}
			} else {
				return pushInstToParentByDefIds(rootTree, defIds);
			}
		} else {
			return pushInstToParentByDefIds(rootTree, defIds);
		}
	} catch (e) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log(
				'CIF.CT.componentTree.ComponentTreeHelper:addNewInstancesToTreeByDefIds error',
				e
			);
		}
		throw e;
	}
};

const addNewInstancesToTreeByDefIds = (rootTree = [], defIds = [], parentNodeId = '') => {
	const result = _addNewInstancesToTreeByDefIds(rootTree, defIds, parentNodeId);
	getTreeFlatLayer(rootTree);
	return result;
};

/**
 * 组件树通过树节点id批量删除树节点辅助函数
 * 删除失败不提供回滚
 * @param {ComponentTreeNode[]} rootTree
 * @param {ComponentTreeNode[] | String[]} treeNodeOrIds
 * @returns 全部删除成功返回true，有失败的话返回false
 */
const _deleteTreeNodeToTreeByIds = (rootTree = [], treeNodeOrIds = []) => {
	return treeNodeOrIds
		.map((treeNodeOrId) => {
			const treeNodeDetail = findTreeNodeDetail(
				rootTree,
				treeNodeOrId instanceof ComponentTreeNode ? treeNodeOrId.uuid : treeNodeOrId
			);
			if (!_.isEmpty(treeNodeDetail.cpntTreeNode)) {
				if (!_.isEmpty(treeNodeDetail.parent.children)) {
					delete treeNodeDetail.parent.children.splice(treeNodeDetail.indexOfParent, 1);
				} else if (_.isArray(treeNodeDetail.parent)) {
					delete treeNodeDetail.parent.splice(treeNodeDetail.indexOfParent, 1);
				}
				return true;
			}
			return false;
		})
		.findIndex((x) => x === false) === -1
		? true
		: false;
};

const deleteTreeNodeToTreeByIds = (rootTree = [], treeNodeOrIds = []) => {
	const result = _deleteTreeNodeToTreeByIds(rootTree, treeNodeOrIds);
	getTreeFlatLayer(rootTree);
	return result;
};

/**
 * 删除树节点
 * @param {ComponentTreeNode[]} rootTree
 * @param {ComponentTreeNode | String} treeNodeOrId
 * @returns 删除成功返回true，失败返回false
 */
const _deleteTreeNodeToTree = (rootTree = [], treeNodeOrId) => {
	// debugger;
	// const treeNodeDetail = findTreeNodeDetail(
	// 	rootTree,
	// 	treeNodeOrId instanceof ComponentTreeNode ? treeNodeOrId.uuid : treeNodeOrId
	// );
	// if (!_.isEmpty(treeNodeDetail.cpntTreeNode)) {
	// 	if (!_.isEmpty(treeNodeDetail.parent.children)) {
	// 		delete treeNodeDetail.parent.children.splice(treeNodeDetail.indexOfParent, 1);
	// 	} else if (_.isArray(treeNodeDetail.parent)) {
	// 		delete treeNodeDetail.parent.splice(treeNodeDetail.indexOfParent, 1);
	// 	}
	// 	return true;
	// }
	// return false;
	const treeNodeDetail = findTreeNodeDetail(
		rootTree,
		treeNodeOrId instanceof ComponentTreeNode ? treeNodeOrId.uuid : treeNodeOrId
	);
	if (_.isEmpty(treeNodeDetail.cpntTreeNode)) {
		return false;
	}
	const parent = treeNodeDetail.parent;
	if (parent && parent.children) {
		parent.children.splice(treeNodeDetail.indexOfParent, 1);
	} else if (Array.isArray(parent)) {
		parent.splice(treeNodeDetail.indexOfParent, 1);
	}
	return true;
};

const deleteTreeNodeToTree = (rootTree = [], treeNodeOrId) => {
	const result = _deleteTreeNodeToTree(rootTree, treeNodeOrId);
	getTreeFlatLayer(rootTree);
	return result;
};

/**
 * 组件树节点批量成组操作，当所传入组件树节点均是同一父节点下的节点时，在父节点
 * @param {ComponentTreeNode[]} rootTree
 * @param {String[]} treeNodesToGrouped
 * @returns 成组成功返回true，失败返回false
 */
const _groupToFolder = (rootTree = [], treeNodesIdToGrouped = []) => {
	if (treeNodesIdToGrouped.length <= 1) {
		if (_.get(window, 'cif.config.logger.enable', false) === true) {
			console.log(
				'CIF.CT.componentTree.ComponentTreeHelper:groupToFolder 需要两个以上节点才能成组'
			);
		}
		return false;
	}
	const emptyFolder = new ComponentTreeNode();

	const treeNodeDetails = treeNodesIdToGrouped.map((id) => {
		return findTreeNodeDetail(rootTree, id);
	});

	// 计算是否是同一父节点下的节点
	let isHasSameParent = false;
	const firstTreeNodeObj = treeNodeDetails[0];
	for (let i = 1; i < treeNodeDetails.length; i++) {
		if (firstTreeNodeObj.parent === treeNodeDetails[i].parent) {
			isHasSameParent = true;
			break;
		}
	}

	treeNodeDetails.forEach((treeNodeObj) => {
		emptyFolder.children.push(treeNodeObj.cpntTreeNode);
		if (!_.isEmpty(treeNodeObj.parent.children)) {
			delete treeNodeObj.parent.children.splice(treeNodeObj.indexOfParent, 1);
		} else if (_.isArray(treeNodeObj.parent)) {
			delete treeNodeObj.parent.splice(treeNodeObj.indexOfParent, 1);
		}
		// delete treeNode.parent.splice(treeNode.indexOfParent, 1)
	});
	if (isHasSameParent) {
		// 根节点没有uuid
		if (firstTreeNodeObj.parent.uuid && firstTreeNodeObj.cpntTreeNode.isAllowHasChilds()) {
			addTreeNodeToTree(rootTree, emptyFolder, firstTreeNodeObj.parent.uuid);
		} else {
			addTreeNodeToTree(rootTree, emptyFolder);
		}
	} else {
		addTreeNodeToTree(rootTree, emptyFolder);
	}
	return true;
};

const groupToFolder = (rootTree = [], treeNodesIdToGrouped = []) => {
	const result = _groupToFolder(rootTree, treeNodesIdToGrouped);
	getTreeFlatLayer(rootTree);
	return result;
};

/**
 * 保存组件树，但不保存组件定义的引用
 * @param {ComponentTreeNode[]} treeData
 * @returns 组件树JSON字符串
 */
const saveTree = (treeData = []) => {
	const replacer = (key, value) => {
		// TODO consider remove all properties starts with __
		if (key === 'definitionRefrence') {
			return undefined;
		}
		return value;
	};

	const defDict = {};

	//循环处理数据
	const detail = (treeNode) => {
		if (treeNode.nodeType !== ComponentTreeNodeTypeEnum.FOLDER) {
			const defId = _.get(treeNode, 'componentInstance.definitionId', null);
			if (!_.isNil(defId)) {
				const count = _.get(defDict, `${defId}`, 0);
				defDict[defId] = count + 1;
			}
		}
		if (!_.isNil(treeNode.children) && !_.isEmpty(treeNode.children)) {
			treeNode.children.forEach((childrenTreeNode) => {
				detail(childrenTreeNode);
			});
		}
	};
	treeData.forEach((treeNode) => {
		detail(treeNode);
	});
	const referenceComponent = Object.keys(defDict).map((key) => {
		return {
			componentId: key,
			refrenceTime: defDict[key]
		};
	});
	StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_REFRENCE_COMPONENT_CFG, referenceComponent);
	return zip(JSON.stringify(treeData, replacer));
};

export default ComponentTreeNode;

export const ComponentTreeHelper = {
	initTree,
	getNewTree,
	addTreeNodeToTree,
	addNewInstancesToTreeByDefIds,
	deleteTreeNodeToTreeByIds,
	deleteTreeNodeToTree,
	findTreeNodeQuick,
	findTreeNodeDetail,
	groupToFolder,
	saveTree,
	getTreeFlatLayer
};
